package com.feonix.common.util;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.utils.URIBuilder;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;

public class StringUtil {

	private static final Log logger = LogFactory.getLog(StringUtil.class);

	String MOBILE = "^1(3[0-9]|5[0-35-9]|8[05-9])\\d{8}$";

	String CM = "^1(34[0-8]|(3[5-9]|5[017-9]|8[78])\\d)\\d{7}$";

	String CU = "^1(3[0-2]|5[256]|8[56])\\d{8}$";

	String CT = "^1((33|53|8[09])[0-9]|349)\\d{7}$";

	String PHS = "^0(10|2[0-5789]|\\d{3})\\d{7,8}$";

	public static final String[][] SAFESTRING_REPLACE = { { "\"", "'" }, { "&quot;", "&apos;" } };

	/**
	 * URL编码--默认使用utf-8编码
	 * @param str
	 * @return
	 */
	public static String encoder(String str) {
		try {
			if (str == null) {
				return "";
			}
			str = URLEncoder.encode(str, "utf-8");
		} catch (UnsupportedEncodingException unsupportedEncodingException) {
			logger.error("encoder error", unsupportedEncodingException);
		}
		return str;
	}

	public static String decoder(String str) {
		try {
			if (str == null) {
				return "";
			}
			str = URLDecoder.decode(str, "utf-8");
		} catch (UnsupportedEncodingException unsupportedEncodingException) {
			logger.error("decoder error", unsupportedEncodingException);
		}
		return str;
	}

	public static String escapeHTML(String string) {
		if (string == null) {
			return null;
		}
		return freemarker.template.utility.StringUtil.HTMLEnc(string);
	}

	public static String escapeJS(String string) {
		if (string == null) {
			return null;
		}
		return freemarker.template.utility.StringUtil.javaScriptStringEnc(string);
	}

	@Deprecated
	public static String getSafeString(String str, boolean isForce) {
		return getSafeString(str);
	}

	/**
	 * 获得安全的字符串（过滤xss），此方法会去除html字符串并且转义特殊字符
	 * 
	 * @param str
	 * @return
	 */
	public static String getSafeString(String str) {
		str = getString(str);
		str = removeHTML(str);
		str = StringUtils.replaceEach(str, SAFESTRING_REPLACE[0], SAFESTRING_REPLACE[1]);
		str = replace(str, "%3C", "&#60;", true);
		str = replace(str, "%3E", "&#62;", true);
		str = replace(str, "javascript", "ｊａｖａｓｃｒｉｐｔ", true);
		str = replace(str, "expression", "ｅｘｐｒｅｓｓｉｏｎ", true);
		str = replace(str, "%250D%250A", " ", true);
		str = replace(str, "%0D%0A", " ", true);
		str = replace(str, "%0A", " ", true);
		return str;
	}

	/**
	 * 清除html标签，比如：<a>123456</a>，被清理成123456
	 * 
	 * @param str
	 * @return
	 */
	public static String removeHTML(String str) {
		if (isNotEmpty(str)) {
			Whitelist whitelist = new Whitelist();
			str = Jsoup.clean(str, whitelist);
		}
		return str;
	}

	/**
	 * 清除回车换行
	 * 
	 * @param str
	 * @return
	 */
	public static String removeEnter(String str) {
		return StringUtils.replaceEach(str, new String[] { "\n", "\r" }, new String[] { "", "" });
	}

	/**
	 * 清除所有空格包含制表符
	 * 
	 * @param str
	 * @return
	 */
	public static String removeWhitespace(String str) {
		return StringUtils.deleteWhitespace(str);
	}

	/**
	 * 转义xhtml
	 * 
	 * @param string
	 * @return
	 */
	public static String escapeXHTML(String string) {
		if (string == null) {
			return null;
		}
		return freemarker.template.utility.StringUtil.XHTMLEnc(string);
	}

	/**
	 * 删除字符
	 * 
	 * @param str
	 *            源字符串
	 * @param removeStr
	 *            要删除的字符
	 * @return
	 */
	public static String removeString(String str, String removeStr) {
		return StringUtils.remove(str, removeStr);
	}

	/**
	 * 转义sql中的特殊字符
	 * 
	 * @param string
	 * @return
	 */
	public static String escapeXml(String string) {
		if (string == null) {
			return null;
		}
		return freemarker.template.utility.StringUtil.XMLEnc(string);
	}

	/**
	 * 从一个object 转换到 string，如果为null 则返回""
	 * 
	 * @param object
	 * @return
	 */
	public static String getString(Object object) {
		return ObjectUtils.toString(object, "");
	}

	/**
	 * 从一个object 转换到 string，如果为null 则返回“”
	 * 
	 * @param object
	 * @param defString
	 * @return
	 */
	public static String getString(Object object, String defString) {
		String str = ObjectUtils.toString(object, defString);
		if (isEmpty(str)) {
			str = defString;
		}
		return str;
	}

	/**
	 * 截取字符串
	 * 
	 * @param str
	 *            源字符串
	 * @param start
	 *            开始
	 * @param end
	 *            结束
	 * @return
	 */
	public static String subString(String str, String start, String end) {
		return StringUtils.substringBetween(str, start, end);
	}

	/**
	 * 从一个object 转换到 string并且trim，如果为null 则返回“”
	 * 
	 * @param object
	 * @return
	 */
	@Deprecated
	public static String getStringTrim(Object object) {
		return ObjectUtils.toString(object, "").trim();
	}

	/**
	 * 从一个object 转换到 string并且trim，如果为null 则返回“”
	 * 
	 * @param object
	 * @return
	 */
	public static String trim(Object object) {
		return ObjectUtils.toString(object, "").trim();
	}

	/**
	 * 字符串替换
	 * 
	 * @param text
	 * @param searchString
	 * @param replacement
	 * @return
	 */
	public static String replace(String text, String searchString, String replacement) {
		return StringUtils.replace(text, searchString, replacement);
	}

	/**
	 * 字符串替换
	 * 
	 * @param text
	 *            源字符串
	 * @param searchString
	 *            被替换的字符
	 * @param replacement
	 *            新字符
	 * @param caseInsensitive
	 *            是否忽略大小写
	 * @return
	 */
	public static String replace(String text, String searchString, String replacement, boolean caseInsensitive) {
		if (text == null) {
			return null;
		}
		return freemarker.template.utility.StringUtil.replace(text, searchString, replacement, caseInsensitive, false);
	}

	/**
	 * 替换第一个出现的字符串
	 * 
	 * @param text
	 *            源字符串
	 * @param searchString
	 *            被替换的字符
	 * @param replacement
	 *            新字符
	 * @return
	 */
	public static String replaceFirst(String text, String searchString, String replacement) {
		return StringUtils.replaceOnce(text, searchString, replacement);
	}

	/**
	 * 获得32位唯一码
	 * 
	 * @return
	 */
	public static String getUUIDString() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	/**
	 * 将一个字符串转换成一个 integer 类型数组
	 * 
	 * @param str
	 * @return
	 */
	@Deprecated
	public static Integer[] getIntegerArray(String str) {
		if ((str == null) || (str.trim().length() == 0)) {
			return null;
		}
		String[] arrayOfString = str.split(",");
		Integer[] arrayOfInteger = null;
		if ((arrayOfString != null) && (arrayOfString.length > 0)) {
			arrayOfInteger = new Integer[arrayOfString.length];
			for (int i = 0; i < arrayOfString.length; ++i) {
				arrayOfInteger[i] = Integer.valueOf(Integer.parseInt(arrayOfString[i]));
			}
		}
		return arrayOfInteger;
	}

	/**
	 * 把集合装换为字符串
	 * 
	 * @param collection
	 * @param separator
	 * @return
	 */
	public static String join(Collection<?> collection, String separator) {
		return StringUtils.join(collection, separator);
	}

	/**
	 * 把数组转换为字符串
	 * 
	 * @param array
	 * @param separator
	 * @return
	 */
	public static String join(Object[] array, String separator) {
		return StringUtils.join(array, separator);
	}

	/**
	 * 删除各种stringbuffer里面的内容
	 * 
	 * @param sb
	 */
	public static void cleanStringBuffer(StringBuffer[] sb) {
		for (int i = 0; i < sb.length; ++i)
			sb[i].delete(0, sb[i].length());
	}

	/**
	 * 搜索指定一个字符串在另一个字符串中出现的次数
	 * 
	 * @param paramString1
	 * @param paramString2
	 * @return
	 */
	public static int countMatches(String string, String sub) {
		return StringUtils.countMatches(string, sub);
	}

	/**
	 * 判断一个字符串中是否含有指定的字符串
	 * 
	 * @param string
	 * @param searchStr
	 * @return
	 */
	public static boolean contains(String string, String searchStr) {
		return StringUtils.contains(string, searchStr);
	}

	/**
	 * 返回一个指定重复次数的字符串
	 * 
	 * @param string
	 * @param frequency
	 * @return
	 */
	public static String repeat(String string, int frequency) {
		return StringUtils.repeat(string, frequency);
	}

	/**
	 * 将string数组转换成integer数组
	 * 
	 * @param strArr
	 * @return
	 */
	public static Integer[] toIntegerArray(String[] strArr) {
		if (strArr == null) {
			return null;
		}
		Integer[] arrayOfInteger = new Integer[strArr.length];
		for (int i = 0; i < strArr.length; ++i) {
			arrayOfInteger[i] = Integer.valueOf(Integer.parseInt(strArr[i]));
		}
		return arrayOfInteger;
	}

	/**
	 * 将url前面加上 "/" 符号.
	 * 
	 * @param url
	 * @param split
	 * @return
	 */
	public static String paresUrl(String url, String split) {
		if ((url == null) || (url.trim().length() == 0)) {
			return url;
		}
		url = StringUtils.replace(url, "\\", "/");
		String[] arrayOfString = StringUtils.split(url, split);
		StringBuffer stringBuffer = new StringBuffer(0);
		for (int i = 0; i < arrayOfString.length; ++i) {
			if ((split != null) && (split.length() > 0)) {
				stringBuffer.append(split);
			}
			if (!(arrayOfString[i].startsWith("/"))) {
				stringBuffer.append("/");
			}
			stringBuffer.append(arrayOfString[i]);
		}
		if ((split != null) && (split.length() > 0)) {
			stringBuffer.delete(0, 1);
		}
		url = stringBuffer.toString();
		cleanStringBuffer(new StringBuffer[] { stringBuffer });
		return url;
	}

	/**
	 * 将path转换成 xxx/xxx/xxx
	 * 
	 * @param path
	 * @param fix
	 * @return
	 */
	public static String convertPath(String path, boolean fix) {
		if (isEmpty(path)) {
			return path;
		}
		path = StringUtils.replace(path, "\\", "/");
		if ((fix) && (!(path.endsWith("/")))) {
			path = path + "/";
		}
		return path;
	}

	/**
	 * equals，不会空指针
	 * 
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static boolean equals(String str1, String str2) {
		return StringUtils.equals(str1, str2);
	}

	/**
	 * 不区分大小写比较 equalsIgnoreCase，不会空指针
	 * 
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static boolean equalsIgnoreCase(String str1, String str2) {
		return StringUtils.equalsIgnoreCase(str1, str2);
	}

	/**
	 * 判断是否为空（自动trim）
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str) {
		return StringUtils.isBlank(str);
	}

	/**
	 * 判断是否为空（自动trim）
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNotEmpty(String str) {
		return StringUtils.isNotBlank(str);
	}

	/**
	 * 拆分字符串为数组
	 * 
	 * @param str
	 * @param separatorChar
	 * @return
	 */
	public static String[] split(String str, String separatorChar) {
		return StringUtils.splitByWholeSeparator(str, separatorChar);
	}

	/**
	 * 将string转换成String list
	 * 
	 * @param str
	 * @param separatorChar
	 * @return
	 */
	public static List<String> toStringList(String str, String separatorChar) {
		String[] arrayOfString = split(str, separatorChar);
		return Arrays.asList(arrayOfString);
	}

	/**
	 * 将string转换成String list 默认以,分割
	 * 
	 * @param str
	 * @return
	 */
	public static List<String> toStringList(String str) {
		return toStringList(str, ",");
	}

	/**
	 * 将string转换成Integer list
	 * 
	 * @param str
	 * @param separatorChar
	 * @return 如果string切分后的字符串不能转换为intger，就会返回null
	 */
	public static List<Integer> toIntegerList(String str, String separatorChar) {
		String[] arrayOfString1 = split(str, separatorChar);
		ArrayList<Integer> arrayList = new ArrayList<Integer>();
		if (arrayOfString1 != null) {
			for (String tmpStr : arrayOfString1) {
				if (NumberUtil.isNotNumeric(tmpStr)) {
					return null;
				}
				arrayList.add(Integer.valueOf(NumberUtil.getInt(tmpStr)));
			}
		}
		return arrayList;
	}

	/**
	 * 将string转换成Integer list ，默认以,分割
	 * 
	 * @param str
	 * @return
	 */
	public static List<Integer> toIntegerList(String str) {
		return toIntegerList(str, ",");
	}

	/**
	 * 按字节长度截取字符串，默认编码为u8
	 * 
	 * @param str
	 * @param toCount
	 * @return
	 */
	public static String limitLen(String str, int toCount) {
		return limitLen(str, toCount, "utf-8");
	}

	/**
	 * 按字节长度截取字符串
	 * 
	 * @param str
	 * @param toCount
	 * @param charset
	 * @return
	 */
	public static String limitLen(String str, int toCount, String charset) {
		int i = 0;
		String str1 = "";
		if ((str != null) && (str.length() > 0)) {
			if ((charset == null) || (charset.length() == 0))
				charset = "UTF-8";
			try {
				int j = 0;
				j = str.getBytes(charset).length;
				if (j <= toCount) {
					str1 = str;
					return str1;
				}
				char[] arrayOfChar = str.toCharArray();
				for (int k = 0; k < arrayOfChar.length; ++k) {
					String str2 = String.valueOf(arrayOfChar[k]);
					byte[] arrayOfByte = str2.getBytes("UTF-8");
					i += arrayOfByte.length;
					if (i < toCount) {
						str1 = str1 + arrayOfChar[k];
					}
				}
			} catch (Exception exception) {
				logger.error("截取字符串长度时发生异常!", exception);
			}
		}
		return str1;
	}

	/**
	 * 判断字符串是否超过指定长度,超过长度将进行截取,截取后增加后缀字符
	 * 
	 * @param str
	 * @param toCount
	 * @param charset
	 * @param strTag
	 * @return
	 */
	public static String limitLen(String str, int toCount, String charset, String strTag) {
		strTag = getString(strTag);
		int i = 0;
		String str1 = "";
		if ((str != null) && (str.length() > 0)) {
			if ((charset == null) || (charset.length() == 0))
				charset = "UTF-8";
			try {
				int j = 0;
				j = str.getBytes(charset).length;
				if (j <= toCount) {
					str1 = str;
					return str1;
				}
				char[] arrayOfChar = str.toCharArray();
				for (int k = 0; k < arrayOfChar.length; ++k) {
					String str2 = String.valueOf(arrayOfChar[k]);
					byte[] arrayOfByte = str2.getBytes("UTF-8");
					i += arrayOfByte.length;
					if (i >= toCount)
						break;
					str1 = str1 + arrayOfChar[k];
				}
				str1 = str1 + strTag;
			} catch (Exception exception) {
				logger.error("截取字符串长度时发生异常!", exception);
			}
		}
		return str1;
	}

	/**
	 * 获得完整路径
	 * 
	 * @param baseUrl
	 * @param url
	 * @return
	 */
	public static String toFullUrl(String baseUrl, String url) {
		try {
			if ((isNotEmpty(baseUrl)) && (!(contains(replace(baseUrl, "//", ""), "/")))) {
				baseUrl = baseUrl + "/";
			}
			java.net.URI uri1 = new java.net.URI(baseUrl);
			java.net.URI uri2 = uri1.resolve(url);
			URL uri = uri2.toURL();
			url = uri.toString();
		} catch (Exception exception) {
		}
		return url;
	}

	/**
	 * 根据字典将 1,2,34,4 转换成 xx,yyy,yyy,vvv
	 * 
	 * @param keys
	 * @param dic
	 * @return
	 */
	public static String convertToDicValue(String keys, Map<String, String> dic) {
		String str1 = null;
		if (isNotEmpty(keys)) {
			String[] arrayOfString = split(keys, ",");
			ArrayList<String> arrayList = new ArrayList<String>();
			for (int i = 0; i < arrayOfString.length; ++i) {
				String str2 = arrayOfString[i];
				String str3 = dic.get(str2);
				if (isNotEmpty(str3)) {
					arrayList.add(str3);
				}
			}
			str1 = join(arrayList, ",");
		}
		return str1;
	}

	/**
	 * 根据字典将 1,2,34,4 转换成 xx,yyy,yyy,vvv
	 * 
	 * @param keys
	 * @param dic
	 * @return
	 */
	public static String convertToDicValue(String keys, Properties dic) {
		String str1 = null;
		if (isNotEmpty(keys)) {
			String[] arrayOfString = split(keys, ",");
			ArrayList<String> arrayList = new ArrayList<String>();
			for (int i = 0; i < arrayOfString.length; ++i) {
				String str2 = arrayOfString[i];
				String str3 = dic.getString(str2);
				if (isNotEmpty(str3)) {
					arrayList.add(str3);
				}
			}
			str1 = join(arrayList, ",");
		}
		return str1;
	}

	/**
	 * 获得异常堆栈
	 * 
	 * @param e
	 * @return
	 */
	public static String getExceptionString(Throwable e) {
		return ExceptionUtils.getStackTrace(e);
	}

	private static boolean isChinese(char c) {
		Character.UnicodeBlock localUnicodeBlock = Character.UnicodeBlock.of(c);

		return ((localUnicodeBlock == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
				|| (localUnicodeBlock == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS)
				|| (localUnicodeBlock == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A)
				|| (localUnicodeBlock == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B)
				|| (localUnicodeBlock == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION)
				|| (localUnicodeBlock == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS)
				|| (localUnicodeBlock == Character.UnicodeBlock.GENERAL_PUNCTUATION));
	}

	public static boolean isChinese(String strName) {
		if (isEmpty(strName)) {
			return false;
		}
		char[] arrayOfChar = strName.toCharArray();
		for (int i = 0; i < arrayOfChar.length; ++i) {
			char c1 = arrayOfChar[i];
			if (isChinese(c1)) {
				return true;
			}
		}
		return false;
	}

	public static boolean isChineseByREG(String str) {
		if (isEmpty(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("[\\u4E00-\\u9FBF]+");
		return pattern.matcher(str.trim()).find();
	}

	public static boolean isChineseByName(String str) {
		if (isEmpty(str)) {
			return false;
		}

		String pp = "\\p{InCJK Unified Ideographs}&amp;&amp;\\P{Cn}";
		Pattern pattern = Pattern.compile(str);
		return pattern.matcher(pp.trim()).find();
	}

	/**
	 * url编码
	 * 
	 * @param url
	 * @return
	 */
	public static String encodeUrl(String url) {
		return encodeUrl(url, "utf-8");
	}

	/**
	 * url编码
	 * 
	 * @param url
	 * @param charset
	 * @return
	 */
	public static String encodeUrl(String url, String charset) {
		if ((isNotEmpty(url)) && (isNotEmpty(url))) {
			try {
				URIBuilder ub = new URIBuilder(new URI(url));
				ub.setCharset(Charset.forName(charset));
				url = ub.toString();
			} catch (Exception exception) {
				logger.error("urlEncode error", exception);
			}
		}
		return url;
	}

	/**
	 * 将url中的中文变成 utf-8，如果没有返回原url
	 * 
	 * @param url
	 * @return
	 */
	public static String encodeChineseUrl(String url) {
		return encodeChineseUrl(url, "utf-8");
	}

	/**
	 * 将url中的中文变成指定编码，如果没有返回原url
	 * 
	 * @param url
	 * @param charset
	 * @return
	 */
	public static String encodeChineseUrl(String url, String charset) {
		if ((isChinese(url)) && (isNotEmpty(charset))) {
			url = encodeUrl(url, charset);
		}
		return url;
	}

}
